package com.ruoyi.job.task;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.JsonUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.job.mapper.FeeProjectMapper;
import com.ruoyi.omp.api.RemoteBillService;
import com.ruoyi.omp.api.RemoteLeaseRecordService;
import com.ruoyi.omp.api.domain.FeApartment;
import com.ruoyi.omp.api.domain.FeApartmentBill;
import com.ruoyi.omp.api.domain.FeApartmentLeaseDetail;
import com.ruoyi.omp.api.enums.FeeTypeEnum;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

//import com.sun.xml.internal.ws.binding.FeatureListUtil;

/**
 * @author: cjie
 * @description: 定时生成公寓账单
 * @date: 2021/9/23
 */
@Component("billFeApartTask")
public class FeApartTask {
    private static final Logger logger = LoggerFactory.getLogger(FeApartTask.class);
/*    @Autowired
    private RemoteLeaseRecordService leaseRecordService;
    @Autowired
    private RemoteRoomService roomService;*/
/*    @Autowired
    private RemoteLeaseRecordService remoteLeaseRecordService;*/

    @Autowired
    private FeeProjectMapper feeProjectMapper;
    @Autowired
    private RemoteBillService billService;

    @Autowired
    private RedisService redisService;

    /** 提前 orderDay 天生成账单；
     * 定时生成公寓账单
     * delayDay 延期
     *
     * @param orderDay
     */
    public void createApartmentBill(Integer orderDay, Integer delayDay) {
        //当前日期
        Date date = DateUtil.date();
        // 查询公寓收费是否到期
        List<FeApartment> apartments = feeProjectMapper.selectFeApartment("未到期", "已生效", "自动计费");
        for (FeApartment apartment : apartments) {
            //账单约定日期
            Date nextDate = apartment.getNextPropertyDate();
            //过滤记录
            if (nextDate == null) {
                logger.error(apartment.getLeaseNum()+"下期账单生成时间为空！");
                continue;
            }
            if (nextDate.compareTo(apartment.getEndTime()) >= 0) {
                // 设置成已到期
                apartment.setRecordState("已到期");
                //feeProjectMapper.updateFeApartment(apartment);

                logger.info(apartment.getLeaseNum()+ ": 已到期，" + "生成账单日期"+ DateUtils.dateTime(apartment.getNextPropertyDate())+",结束时间" + DateUtils.dateTime(apartment.getEndTime()));
                continue;
            }

            long betweenDay = DateUtil.between(nextDate, date, DateUnit.DAY);
            //计算费用
            if (betweenDay <= orderDay) {
                FeApartmentBill feBill = new FeApartmentBill();

                //计算账单起止日期及月份，0按月|1按季度,
                BigDecimal month = computeStartAndEndTime(apartment,feBill);

                //按月计算
                if ("按面积".equals(apartment.getLeaseModel())) {
                    //设施使用费、物业费
                    BigDecimal area = apartment.getContractArea();
                    //租金
                    feBill.setRental(apartment.getAreaPrice().multiply(area).multiply(month));
                    //物管费
                    if(apartment.getPropertyPrice() !=  null){
                        feBill.setPropertyFee(apartment.getPropertyPrice().multiply(area).multiply(month));
                    }
                    //设施使用费
                    if(apartment.getFacilityPrice() != null){
                        feBill.setFacilityFee(apartment.getFacilityPrice().multiply(area).multiply(month));
                    }
                    feBill.setReceivableAmount(feBill.getFacilityFee().add(feBill.getPropertyFee()));

                } else if ("按间".equals(apartment.getLeaseModel())) {
                    // 公寓租赁详情，公寓账单，账单组合；租金，物业费
                    List<FeApartmentLeaseDetail> apartDetailList = feeProjectMapper.selectFeApartmentDetailList(apartment.getId());
                    if (apartDetailList.size()>0) {
                        //rental = roomVOr.getData().stream().map(RoomVO::getAreaPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                        for(FeApartmentLeaseDetail detail:apartDetailList){
                            if(detail.getRent() != null){
                                feBill.setRental(feBill.getRental().add(detail.getRent()));
                            }
                            if(detail.getFeProperty() != null){
                                feBill.setPropertyFee(feBill.getPropertyFee().add(detail.getFeProperty()));
                            }
                        }
                        feBill.setRental(feBill.getRental().multiply(month));
                        feBill.setPropertyFee(feBill.getPropertyFee().multiply(month));
                        feBill.setReceivableAmount(feBill.getRental().add(feBill.getPropertyFee()));
                    }
                }
                //更新下一次费收取日期
                feeProjectMapper.updateFeApartment(apartment);

                //租赁记录详情，
                List<String> apartmentDetails = feeProjectMapper.selectFeApartmentDetails(apartment.getId());

                feBill.setEnterpriseId(apartment.getEnterpriseId());
                feBill.setFeeType(FeeTypeEnum.APARTMENT.getCode());
                feBill.setFeeTypeName(FeeTypeEnum.APARTMENT.getType());
                feBill.setBillNum(genBillCode());
                feBill.setPayState("0");
                feBill.setDeadline(DateUtil.offsetDay(nextDate, delayDay));
                feBill.setRecordId(apartment.getId());
                feBill.setTotalArea(apartment.getContractArea());
                feBill.setUnitPrice(apartment.getAreaPrice());
                feBill.setEnterpriseName(apartment.getEnterpriseName());
                feBill.setDetails(JsonUtils.covertList2One(apartmentDetails));
                //todo 设置账单周期；
                billService.addApartBill(feBill);
                logger.info(apartment.getLeaseNum() +" " + DateUtils.dateTime(feBill.getBeginDate()) + "到" + DateUtils.dateTime(feBill.getEndDate()));
            }

        }
    }


    private String genBillCode() {
        String date = DateUtil.format(DateUtil.date(), "yyyyMMdd");
        Integer v = redisService.getCacheObject(date);

        String result = "";
        if (v == null) {
            v = 0;
            redisService.setCacheObject(date, v);
            redisService.expire(date, 24 * 60 * 60);
        } else {
            v = v + 1;
            redisService.setCacheObject(date, v);
        }

        String fs = String.format("%03d", v);
        result = "B" + date + fs;
        return result;
    }


    @Test
    public void testDate(){
        //下一次账单日期
        int month = 3;
        Date endTime = DateUtil.parseDate("2022-12-28");
        Date nextDate = DateUtil.parseDate("2022-10-28");
        //下一次账单日期
        for (int i = 1; i <= 3; i++) {
            Date nextDay = DateUtil.offsetMonth(nextDate, i);
            int com = DateUtil.compare(endTime, nextDay);
            if (com < 0) {
                System.out.println("next date:" + endTime);
                break;
            }
            month = i;
        }

        System.out.println("month:" + month);
    }

    private BigDecimal computeMonth(Date begin,Date end){
        BigDecimal month = BigDecimal.valueOf(0);
        //begin < end
        int i =0;
        Date newBegin= DateUtil.offsetMonth(begin,i);
        while (DateUtil.compare(newBegin,end)<0){
            i++;
            newBegin= DateUtil.offsetMonth(begin,i);
        }
        i=i-1;
        long unitDay = DateUtil.between(DateUtil.offsetMonth(begin,i),end,DateUnit.DAY);
        BigDecimal unitMonth = BigDecimal.valueOf(unitDay).divide(BigDecimal.valueOf(30),4, RoundingMode.HALF_UP);
        month = BigDecimal.valueOf(i).add(unitMonth) ;

        return month;
    }

    //计算账单起止日期及月份
    public BigDecimal computeStartAndEndTime(FeApartment apartment, FeApartmentBill feBill){
        //开始日期
        Date nextDate = apartment.getNextPropertyDate();

        //计算账单起止日期，月份
        BigDecimal month = BigDecimal.valueOf(0);
        feBill.setBeginDate(nextDate);
        //0按月|1按季度,计算下期收费账单时间，
        if ("按季度".equals(apartment.getFeeModel())) {
            //下一次收费日期
            Date nextDay = DateUtil.offsetMonth(nextDate, 3);
            int com = DateUtil.compare(apartment.getEndTime(), nextDay);
            if(com>=0){
                month = BigDecimal.valueOf(3);
                feBill.setEndDate(DateUtil.offsetDay(nextDay,-1));
                apartment.setNextPropertyDate(nextDay);
            }else {
                //不足3个月,不足一个月按天计算，30天
                month = computeMonth(nextDate,apartment.getEndTime());
                feBill.setEndDate(apartment.getEndTime());
                apartment.setNextPropertyDate(apartment.getEndTime());
            }
            // 按月
        }else{
            Date nextDay = DateUtil.offsetMonth(nextDate,1);
            int com = DateUtil.compare(apartment.getEndTime(), nextDay);
            // 足一个月
            if (com >=0) {
                month = BigDecimal.valueOf(1);
                feBill.setEndDate(DateUtil.offsetDay(nextDay,-1));
                apartment.setNextPropertyDate(nextDay);
            }else {
                month = computeMonth(nextDate,apartment.getEndTime());
                feBill.setEndDate(apartment.getEndTime());
                apartment.setNextPropertyDate(apartment.getEndTime());
                //apartment.setRecordState("已到期");
            }

        }
        return month;
    }
}
